home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Languguage OS 2
/
Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO
/
language
/
embedded
/
develop
/
libsrc11.arc
/
AUTOBAUD.C
next >
Wrap
Text File
|
1989-05-04
|
3KB
|
119 lines
/* autobaud.c 4.3 */
/*F****************************************************************
FUNCTION NAME: autobaud
ACTION: Determines Baud Rate setting for SCI Baud register
given E clock and desired baud rate.
PARAMETERS:
E_clock: System clock speed (in 100 hz units).
Baud_Rate: desired baud rate in the form of:
Baud_Rate = baud * 16 / 100
RETURNS: (unsigned)
If autobaud was unsuccessful, 0xFFFF is returned.
If autobaud was successful, then the high byte
of the unsigned is the per cent error for the
baud rate setting (0 to 10%). The low byte
of the returned value is the value for the SCI
BAUD register.
*******************************************************************/
#include <hc11/directives.h>
#define EXT_PRECISION 32768 /* extended precision baud rates */
SMALL
unsigned autobaud ( E_clock, baud )
unsigned E_clock, baud ;
{
unsigned try[2] ;
unsigned best, save ;
unsigned short i, j ;
unsigned Error[4] ;
static unsigned prescaler [4] = { 1, 3, 4, 13 } ;
unsigned lng_E_clk[2] ;
unsigned rem[4] ;
unsigned temp[2] ;
/* one hundred as a 32 bit number */
static unsigned hundred[2] = { 0, 100 } ;
best = 0xFFFF ; /* initial value */
lng_E_clk[0] = 0 ;
lng_E_clk[1] = E_clock ;
if (baud > EXT_PRECISION)
{
baud -= EXT_PRECISION ;
/* lng_E_clk *= 100 */
dmulu (lng_E_clk, hundred, lng_E_clk) ;
}
for (i = 0 ; i < 4 ; i++ )
for (j = 0 ; j < 8 ; j++ )
{
/* try = (lng_E_clk) / (long) (prescaler[i] << j) */
temp[0] = 0 ;
temp[1] = prescaler[i] << j ;
ddivu ( lng_E_clk, temp, rem ) ;
try [0] = rem [2] ;
try [1] = rem [3] ;
/* rem has the remainder... */
/* calculate per cent Error */
/* Error = (abs(try - baud) * 100) / baud */
if (try[0] == 0)
{
if ((unsigned) try[1] > baud)
try[1] -= baud ;
else
try[1] = baud - try[1] ;
dmulu (try, hundred, Error) ;
temp[0] = 0 ;
temp[1] = baud ;
ddivu (Error, temp, Error) ;
/* Since first 2 words of Error has remainder */
/* and last 2 words has result of division */
/* Move the result into the first 2 words for */
/* ease of access. */
Error [0] = Error [2] ;
Error [1] = Error [3] ;
/* if not exact, set at least a one percent Error */
if ((rem[0] | rem[1]) != 0)
Error[1] += 1 ;
if ((Error[0] == 0) && (Error[1] <= 10))
/* perhaps a new best... */
if (best > Error[1])
{
best = Error[1] ;
save = (i << 4) | j ;
}
}
}
if (best == 0xFFFF)
return (best) ;
else
return (best << 8 | save) ;
} /* end of autobaud */